package com.fqgj.sentry.policy.server;

import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.JSONUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.exception.enums.ErrorCodeEnums;
import com.fqgj.sentry.policy.client.RuleService;

import com.fqgj.sentry.policy.dao.*;
import com.fqgj.sentry.policy.domain.rule.RuleAddAndUpdateInfo;
import com.fqgj.sentry.policy.domain.rule.RuleColumnInfo;
import com.fqgj.sentry.policy.entity.*;
import com.fqgj.sentry.policy.enums.*;
import com.fqgj.sentry.policy.exception.PolicyErrorCodeEnums;
import com.fqgj.sentry.policy.exception.RuleErrorCodeEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by liupengpeng on 2017/7/29.
 */
@Service
@Transactional
public class RuleServiceImpl implements RuleService {

    @Autowired
    private PcRuleDao pcRuleDao;
    @Autowired
    private PcRuleConditionDao ruleConditionDao;

    @Autowired
    private PcRuleColumnDao ruleColumnDao;

    @Autowired
    private PcPolicyDao policyDao;
    @Autowired
    private PcExecutorDao executorDao;

    @Override
    public List<PcRuleEntity> findRuleListByPolicyId(Long policyId, Integer active, Integer ruleType) {
        return pcRuleDao.selectListByPolicyId(policyId, active, ruleType);
    }

    @Override
    public List<PcRuleEntity> findActiveRuleListByPolicyId(Long policyId, Integer ruleType) {
        return pcRuleDao.findActiveRuleListByPolicyId(policyId, ruleType);
    }

    /**
     * 规则 删除
     *
     * @param ruleIds
     * @return
     */
    @Override
    public Boolean deleteRule(List<Long> ruleIds) {
        if (CollectionUtils.isNotEmpty(ruleIds)) {
            for (Long ruleId : ruleIds) {
                pcRuleDao.deleteRuleById(ruleId);
                //删除  条件集合
                ruleConditionDao.deleteRuleById(ruleId);
                //删除 规则关联字段
                ruleColumnDao.updateDeleteByRuleId(ruleId);
            }
        } else {
            throw new BizException(RuleErrorCodeEnums.rule_not_exist_error);
        }
        return true;
    }


    @Override
    public String findRuleCondition(Long ruleId) {
        //查询规则
        PcRuleEntity ruleEntity = pcRuleDao.selectByPrimaryKey(ruleId);
        PcRuleConditionEntity pcRuleConditionEntity = ruleConditionDao.selectByRuleId(ruleEntity.getId());
        RuleConditionTypeEnum ruleConditionTypeEnum = RuleConditionTypeEnum.getEnumByType(pcRuleConditionEntity.getConditionType());
        switch (ruleConditionTypeEnum) {
            case first_match:
                return pcRuleConditionEntity.getFirstCondition();
            case bad_match:
                return pcRuleConditionEntity.getWorstCondition();
            case weight_match:
                return pcRuleConditionEntity.getWeightCondition();
            case score:
                return pcRuleConditionEntity.getScoreCondition();
        }
        return "";

    }


    /**
     * 规则 激活状态 更新
     *
     * @param ruleIds
     * @return
     */
    @Override
    public Boolean updateRuleActive(List<Long> ruleIds, ActiveEnum activeEnum) {
        if (CollectionUtils.isNotEmpty(ruleIds)) {
            for (Long ruleId : ruleIds) {
                pcRuleDao.updateRuleActive(ruleId, activeEnum.getType());
            }
        } else {
            throw new BizException(RuleErrorCodeEnums.rule_not_exist_error);
        }
        return true;
    }

    /**
     * 根据 规则编码查询规则
     *
     * @param code
     * @return
     */
    @Override
    public List<PcRuleEntity> findRuleListByCode(String code) {
        return pcRuleDao.findRuleListByCode(code);
    }

    /**
     * 规则新增
     *
     * @param addInfo
     * @return
     */
    @Override
    public Boolean addRule(RuleAddAndUpdateInfo addInfo) {
        PcPolicyEntity policyEntity = policyDao.selectByPrimaryKey(addInfo.getPolicyId());
        if (policyEntity == null) {
            throw new BizException(PolicyErrorCodeEnums.policy_not_exist_error);
        }
        if (StringUtils.isEmpty(addInfo.getRule())) {
            throw new BizException(RuleErrorCodeEnums.rule_not_exist_condition_error);
        }
        if (StringUtils.isEmpty(addInfo.getName())) {
            throw new BizException(RuleErrorCodeEnums.rule_name_not_exist_error);
        }
        //保存 规则
        Integer maxCode = pcRuleDao.findMaxCode(addInfo.getPolicySetsId());
        String nowCode = "1";
        if (maxCode != null) {
            nowCode = (maxCode + 1) + "";
        }
        Integer maxSort = pcRuleDao.findMaxSort(addInfo.getPolicySetsId());
        PcExecutorEntity executorEntity = executorDao.selectByPrimaryKey(policyEntity.getExecutorId());
        PcRuleEntity ruleEntity = new PcRuleEntity();
        ruleEntity.setPolicySetsId(addInfo.getPolicySetsId())
                .setExecutorId(addInfo.getExecutorId())
                .setPolicyId(addInfo.getPolicyId())
                .setName(addInfo.getName())
                .setCode(nowCode)
                .setVersion(executorEntity.getVersion())
                .setIsActive(addInfo.getActiveStatus())
                .setRuleType(addInfo.getRuleType())
                .setSort(maxSort == null ? 1 : maxSort + 1);
        ruleEntity = pcRuleDao.insert(ruleEntity);


        //保存规则条件
        PcRuleConditionEntity conditionEntity = new PcRuleConditionEntity();
        conditionEntity.setPolicyId(addInfo.getPolicyId()).setRuleId(ruleEntity.getId());
        Map ruleMap = new HashMap();
        String nowRuleJson = "";
        try {
            ruleMap = JSONUtils.json2map(addInfo.getRule());
            ruleMap.put("ruleId", ruleEntity.getId().toString());
            ruleMap.put("ruleName", addInfo.getName());
            nowRuleJson = JSONUtils.obj2json(ruleMap);
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.json_transform_error);
        }

        if (policyEntity.getType() == PolicyTypeEnum.grade.getType()) {
            conditionEntity.setConditionType(RuleConditionTypeEnum.score.getType());
            conditionEntity.setScoreCondition(nowRuleJson);
        }
        if (policyEntity.getType() == PolicyTypeEnum.rules.getType()) {
            PolicyMatchingTypeEnum policyMatchingTypeEnum = PolicyMatchingTypeEnum.getEnumByType(policyEntity.getMatchingType());
            switch (policyMatchingTypeEnum) {
                case first_match:
                    conditionEntity.setFirstCondition(nowRuleJson);
                    break;
                case bad_match:
                    conditionEntity.setWorstCondition(nowRuleJson);
                    break;
                case weight_match:
                    conditionEntity.setWeightCondition(nowRuleJson);
                    break;
            }
            conditionEntity.setConditionType(policyEntity.getMatchingType());
        }
        ruleConditionDao.insert(conditionEntity);
        //保存 规则相关字段
        saveRuleColumn(addInfo.getColumnInfoList(), ruleEntity.getId());
        return true;
    }


    @Override
    public Boolean updateRule(Long ruleId, RuleAddAndUpdateInfo updateInfo) {
        if (StringUtils.isEmpty(updateInfo.getRule())) {
            throw new BizException(RuleErrorCodeEnums.rule_not_exist_condition_error);
        }
        if (StringUtils.isEmpty(updateInfo.getName())) {
            throw new BizException(RuleErrorCodeEnums.rule_name_not_exist_error);
        }
        //规则 条件
        PcRuleEntity ruleEntity = pcRuleDao.selectByPrimaryKey(ruleId);

        PcRuleConditionEntity conditionEntity = ruleConditionDao.selectByRuleId(ruleEntity.getId());
        if (conditionEntity.getConditionType() == RuleConditionTypeEnum.score.getType()) {
            conditionEntity.setScoreCondition(updateInfo.getRule());
        } else {
            RuleConditionTypeEnum ruleConditionTypeEnum = RuleConditionTypeEnum.getEnumByType(conditionEntity.getConditionType());
            switch (ruleConditionTypeEnum) {
                case first_match:
                    conditionEntity.setFirstCondition(updateInfo.getRule());
                    break;
                case bad_match:
                    conditionEntity.setWorstCondition(updateInfo.getRule());
                    break;
                case weight_match:
                    conditionEntity.setWeightCondition(updateInfo.getRule());
                    break;
            }
        }
        ruleConditionDao.updateByPrimaryKey(conditionEntity);
        //规则 修改
        if (!updateInfo.getName().equals(ruleEntity.getName())) {
            ruleEntity.setName(updateInfo.getName());
            pcRuleDao.updateByPrimaryKey(ruleEntity);
        }
        //保存 规则相关字段
        ruleColumnDao.deleteByRuleId(ruleId);
        saveRuleColumn(updateInfo.getColumnInfoList(), ruleId);
        return true;
    }

    @Override
    public List<PcRuleEntity> findActiveByPolicySetsIdAndExecutorId(Long policySetsId, Long executorId) {
        return pcRuleDao.findActiveByPolicySetsIdAndExecutorId(policySetsId, executorId);
    }

    @Override
    public List<PcRuleConditionEntity> findRuleConditionByPolicyId(Long policyId) {
        return ruleConditionDao.findRuleConditionByPolicyId(policyId);
    }

    /**
     * 保存 规则 字段表
     *
     * @param ruleColumnInfoList
     * @param ruleId
     */
    private void saveRuleColumn(List<RuleColumnInfo> ruleColumnInfoList, Long ruleId) {
        if (CollectionUtils.isNotEmpty(ruleColumnInfoList)) {
            for (RuleColumnInfo ruleColumnInfo : ruleColumnInfoList) {
                //判断该字段 是否已经存在
                PcRuleColumnEntity ruleColumnEntity = new PcRuleColumnEntity();
                ruleColumnEntity.setRuleId(ruleId)
                        .setColumnId(ruleColumnInfo.getColumnId())
                        .setColumnCode(ruleColumnInfo.getColumnCode());
                ruleColumnDao.insert(ruleColumnEntity);
            }
        }
    }


    @Override
    public List<PcRuleConditionEntity> findAll() {
        return ruleConditionDao.findAll();
    }

    @Override
    public PcRuleEntity findCommonRuleByPolicy(Long policyId) {
        return pcRuleDao.findCommonRuleByPolicy(policyId);
    }

    /**
     * 规则  排序
     *
     * @param ruleId
     * @param sort
     * @return
     */
    @Override
    public Boolean updateRuleSort(Long ruleId, Integer sort) {
        return pcRuleDao.updateRuleSort(ruleId, sort);
    }

    @Override
    public PcRuleEntity findById(Long ruleId) {
        return pcRuleDao.selectByPrimaryKey(ruleId);
    }
}
